package udpserver

import (
	//"bufio"
	"bytes"
	"encoding/binary"
	"fmt"
	"net"
	"runtime"
	"strings"
	"sync"
)

// 开始码
const START_CODE = 0x45F9AC5C

// 同步码：  ( 4 BYTES )
const SYNC_CODE = 0xAC8F79B3

// 结束码：  ( 4 BYTES )
const END_CODE = 0x68AB289F

// KTV协议头
type KtvCmdMessage struct {
	StartCode uint32   // 开始码
	Cmd       uint16   // 命令码
	Series    uint16   // 序列号
	ServerID  uint32   // 来源编号 -- 每个服务器都有唯一的编号
	SynCode   uint32   // 同步数据码
	Data      [44]byte // 传输的数据
	EndCode   uint32   // 终止码
}

// 教研同步同步码是否正确
func (m *KtvCmdMessage) IsOK() bool {

	if m.StartCode != START_CODE ||
		m.SynCode != SYNC_CODE ||
		m.EndCode != END_CODE {
		return false
	}

	return true
}

// 清空数据
func (m *KtvCmdMessage) Clear() {

	m.StartCode = 0
	m.SynCode = 0
	m.EndCode = 0
	m.Cmd = 0
	m.Series = 0
	m.ServerID = 0

	for i := 0; i < 44; i++ {
		m.Data[i] = 0
	}

}

// 重置同步码
func (m *KtvCmdMessage) Reset() {
	m.StartCode = START_CODE
	m.SynCode = SYNC_CODE
	m.EndCode = END_CODE
}

// 上面的结构体大小
const KTV_CMD_STRUCT_SIZE = 64

func (m *KtvCmdMessage) StructSize() int {
	return KTV_CMD_STRUCT_SIZE
}

type ResponseWriter interface {

	// the initial 512 bytes of written data to DetectContentType.
	Write([]byte) (int, error)

	// 写入字符串
	WriteString(string) (int, error)

	// 发送缓冲区
	Flush() (int, error)

	FlushTo(*net.UDPAddr) (int, error)

	//重置发送缓冲区
	Reset()
}

// 请求的信息
type Request struct {

	// 服务器对象
	Srv *UdpServer

	// 命令码
	CmdMessage KtvCmdMessage

	Rd *bytes.Reader

	// 协议头部
	RemoteAddr *net.UDPAddr
}

func (r *Request) RemoteIP() string {
	addr := r.RemoteAddr.String()
	pos := strings.Index(addr, ":")
	if pos > 0 {
		return addr[0:pos]
	} else {
		return addr
	}
}

// 响应信息
type response struct {

	// 服务器对象
	Srv *UdpServer

	// 发送缓冲区
	buf *bytes.Buffer
}

func (w *response) Write(data []byte) (n int, err error) {
	return w.write(len(data), data, "")
}

func (w *response) WriteString(data string) (n int, err error) {
	return w.write(len(data), nil, data)
}

// either dataB or dataS is non-zero.
func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err error) {

	if w.buf == nil {
		w.buf = new(bytes.Buffer)
		w.buf.Grow(1024 * 16)
		w.buf.Reset()
	}

	if lenData == 0 {
		return 0, nil
	}

	if dataB != nil {
		return w.buf.Write(dataB)
	} else {
		return w.buf.WriteString(dataS)
	}
}

// 重置缓冲区
func (w *response) Reset() {
	if w.buf != nil {
		w.buf.Reset()
	}
}

// 正在执行发送功能
func (w *response) Flush() (int, error) {

	// 检查是否存在缓冲区
	if w.buf == nil {
		return 0, nil
	}

	total := w.buf.Len()
	if total <= 0 {
		return 0, nil
	}

	if w.Srv.req.RemoteAddr == nil {
		return 0, nil
	}

	// 退出函数时复位发送缓冲区
	defer w.buf.Reset()

	// 发送数据到指定的地址
	return w.Srv.conn.WriteTo(w.buf.Bytes(), w.Srv.req.RemoteAddr)
}

// 正在执行发送功能
func (w *response) FlushTo(remoteAddr *net.UDPAddr) (int, error) {

	// 检查是否存在缓冲区
	if w.buf == nil {
		return 0, nil
	}

	total := w.buf.Len()
	if total <= 0 {
		return 0, nil
	}

	// 退出函数时复位发送缓冲区
	defer w.buf.Reset()

	// 发送数据到指定的地址
	return w.Srv.conn.WriteTo(w.buf.Bytes(), remoteAddr)
}

// 处理接口
type Handler interface {
	ServeKTV(ResponseWriter, *Request)
}

type HandlerFunc func(ResponseWriter, *Request)

// ServeKTV calls f(w, r).
func (f HandlerFunc) ServeKTV(w ResponseWriter, r *Request) {
	f(w, r)
}

//var defaultServer *UdpServer

//  UDP服务器
type UdpServer struct {
	Addr string //  address to listen on, ":http" if empty
	//	Handler CmdHandler
	conn *net.UDPConn

	req *Request // request for this response

	//
	rsp *response

	// 接收缓冲区
	RecvBuffer []byte

	RecvCount int

	Handler Handler // handler to invoke, http.DefaultServeMux if nil

	// 是否已经停止
	IsKilled bool
}

// serverHandler delegates to either the server's Handler or
// DefaultServeMux and also handles "OPTIONS *" requests.
type serverHandler struct {
	srv *UdpServer
}

func (sh serverHandler) ServeKTV(w ResponseWriter, req *Request) {
	handler := sh.srv.Handler
	if handler == nil {
		handler = DefaultServeMux
	}

	handler.ServeKTV(w, req)
}

//// 协议代码处理映射
type ServeMux struct {
	mu       sync.RWMutex
	m        map[uint16]muxEntry
	NotFound muxEntry
}

//
type muxEntry struct {
	h Handler // 处理函数
	c uint16  // CMD命令码
}

// 注册处理函数
func (mux *ServeMux) Handle(cmd uint16, handler Handler) {
	mux.mu.Lock()
	defer mux.mu.Unlock()

	if handler == nil {
		panic("udpserver: nil handler")
	}

	mux.m[cmd] = muxEntry{h: handler, c: cmd}
}

// 注册处理函数
func (mux *ServeMux) HandleNotFound(handler Handler) {
	mux.mu.Lock()
	defer mux.mu.Unlock()

	if handler == nil {
		panic("http: nil handler")
	}

	mux.NotFound.h = handler
}

// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(cmd uint16, handler func(ResponseWriter, *Request)) {
	mux.Handle(cmd, HandlerFunc(handler))
}

// NewServeMux allocates and returns a new ServeMux.
func NewServeMux() *ServeMux { return &ServeMux{m: make(map[uint16]muxEntry)} }

// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = NewServeMux()

// Handle registers the handler for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func Handle(cmd uint16, handler Handler) { DefaultServeMux.Handle(cmd, handler) }

// HandleFunc registers the handler function for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func HandleFunc(cmd uint16, handler func(ResponseWriter, *Request)) {
	DefaultServeMux.HandleFunc(cmd, handler)
}

// ServeKTV dispatches the request to the handler whose
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeKTV(w ResponseWriter, r *Request) {

	for k, v := range mux.m {
		if k == r.CmdMessage.Cmd {
			h := v.h
			h.ServeKTV(w, r)
			return
		}
	}

	//  找不到对应的cmd代码时执行
	if mux.NotFound.h != nil {
		h := mux.NotFound.h
		h.ServeKTV(w, r)
	}

}

// 开始监听端口
func (srv *UdpServer) ListenAndServe() {

	addr, err := net.ResolveUDPAddr("udp", srv.Addr)
	if err != nil {
		fmt.Println("Can't resolve address: ", err)
		return
	}

	conn, err := net.ListenUDP("udp", addr)
	if err != nil {
		fmt.Println("Error listening:", err)
		return
	}

	// 退出函数时执行以下代码
	defer func() {
		if err := recover(); err != nil {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			fmt.Printf("ktv: panic serving  %v\n%s", err, buf)
		}

		// 关闭P连接
		srv.Close()

	}()

	// 初始化条件
	srv.conn = conn

	if srv.rsp == nil {
		srv.rsp = &response{Srv: srv}
	}

	if srv.req == nil {
		srv.req = &Request{Srv: srv}
	}

	if srv.RecvBuffer == nil {
		srv.RecvBuffer = make([]byte, 1024*16)
	}

	// 进入循环
	for srv.IsKilled != true {

		srv.Serve()

	}

}

func (srv *UdpServer) finishRequest() {

	srv.rsp.Flush()
}

//
func (srv *UdpServer) Serve() {

	var err error

	srv.RecvCount, srv.req.RemoteAddr, err = srv.conn.ReadFromUDP(srv.RecvBuffer)
	if err != nil {
		fmt.Println("failed to read UDP msg because of ", err.Error())
		return
	}

	// 检查接收的字节数
	if srv.RecvCount <= 0 {
		return
	}

	// 创建读数据READER
	srv.req.Rd = bytes.NewReader(srv.RecvBuffer[0:srv.RecvCount])

	srv.req.CmdMessage.Clear()

	// 初始化正确的UDP协议内容
	if srv.RecvCount >= srv.req.CmdMessage.StructSize() {
		binary.Read(bytes.NewBuffer(srv.RecvBuffer),
			binary.LittleEndian,
			&srv.req.CmdMessage)

		if srv.req.CmdMessage.IsOK() == false {
			srv.req.CmdMessage.Clear()
		}
	}

	// 处理消息
	serverHandler{srv}.ServeKTV(srv.rsp, srv.req)

	// 消息处理完之后的处理
	srv.finishRequest()

}

// 停止服务
func (srv *UdpServer) Kill() {
	srv.IsKilled = true
	srv.Close()
}

// 关闭服务
func (srv *UdpServer) Close() {
	if srv.conn != nil {
		srv.conn.Close()
		srv.conn = nil
	}
}
